<?php

/**
 * Class of Validate Advance template
 *
 * @author BUI TIEN HIEP
 * @email bthiep@lhv.vn
 */
class ValidateAdvance extends AbstractValidateFactory implements ICreatePolicyFactory {

    /**
     * Constructor
     * @param type $policy
     */
    public function __construct($policy) {
        $this->policy = $policy;
    }

    /**
     * Build advance condition expression
     * @return /ISpecification
     */
    private function createPolicyFactory() {
        $rules = $this->policy['rules'];
        $specification = null;
        $counter = 0;
        foreach ($rules as $rule) {
            $field = $rule['field'];
            $value = $rule['value'];

            if ($counter == 0) {//For first condition
                switch ($rule['operator']) {
                    case Operator::GREATER_THAN:
                        $specification = $this->isGreaterThan($field, $value);
                        break;
                    case Operator::LESS_THAN:
                        $specification = $this->isLessThan($field, $value);
                        break;
                    case Operator::CONTAIN:
                        $specification = $this->isContain($field, $value);
                        break;
                    case Operator::NOT_CONTAIN:
                        $specification = $this->isNotContain($field, $value);
                        break;
                    case Operator::EQUAL:
                        $specification = $this->isEqual($field, $value);
                        break;
                    case Operator::NOT_EQUAL:
                        $specification = $this->isNotEqual($field, $value);
                        break;
                }
            }
            switch ($rule['operator']) {
                case Operator::GREATER_THAN:
                    if ($rule['boolean_associate'] == 'AND') {
                        $specification->and_($this->isGreaterThan($field, $value));
                    } else if ($rule['boolean_associate'] == 'OR') {
                        $specification->or_($this->isGreaterThan($field, $value));
                    }
                    break;
                case Operator::LESS_THAN:
                    if ($rule['boolean_associate'] == 'AND') {
                        $specification->and_($this->isLessThan($field, $value));
                    } else if ($rule['boolean_associate'] == 'OR') {
                        $specification->or_($this->isLessThan($field, $value));
                    }
                    break;
                case Operator::CONTAIN:
                    if ($rule['boolean_associate'] == 'AND') {
                        $specification->and_($this->isContain($field, $value));
                    } else if ($rule['boolean_associate'] == 'OR') {
                        $specification->or_($this->isContain($field, $value));
                    }
                    break;
                case Operator::NOT_CONTAIN:
                    if ($rule['boolean_associate'] == 'AND') {
                        $specification->and_($this->isNotContain($field, $value));
                    } else if ($rule['boolean_associate'] == 'OR') {
                        $specification->or_($this->isNotContain($field, $value));
                    }
                    break;
                case Operator::EQUAL:
                    if ($rule['boolean_associate'] == 'AND') {
                        $specification->and_($this->isEqual($field, $value));
                    } else if ($rule['boolean_associate'] == 'OR') {
                        $specification->or_($this->isEqual($field, $value));
                    }
                    break;
                case Operator::NOT_EQUAL:
                    if ($rule['boolean_associate'] == 'AND') {
                        $specification->and_($this->isNotEqual($field, $value));
                    } else if ($rule['boolean_associate'] == 'OR') {
                        $specification->or_($this->isNotEqual($field, $value));
                    }
                    break;
            }
            $counter++;
        }
        return $specification;
    }

    /**
     * Validate Advance policy template
     * @param type $expenses
     * @return boolean
     */
    public function validate($expenses = array()) {
        $bRet = false;
        if ($this->createPolicyFactory()->isSatistifiedBy($expenses)) {
            $bRet = true;
            $this->message = $this->policy['message'];
        }
        return $bRet;
    }

}
